package com.alinesno.cloud.base.storage.service.strategy;

import cn.hutool.core.lang.UUID;
import com.alinesno.cloud.base.storage.entity.StorageFileEntity;
import com.alinesno.cloud.base.storage.service.StorageService;
import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.errors.InvalidEndpointException;
import io.minio.errors.InvalidPortException;
import io.minio.errors.MinioException;
import net.sf.jmimemagic.Magic;
import net.sf.jmimemagic.MagicMatch;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.xmlpull.v1.XmlPullParserException;

import java.io.File;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 使用MinIO使用上传方式
 * 
 * @author luodong
 *
 */
@Service("minioStorageService")
public class MinIOStrageServiceImpl implements StorageService {

	// 日志记录
	private final static Logger log = LoggerFactory.getLogger(MinIOStrageServiceImpl.class);

	@Value("${storage.minio.host-domain}")
	private String host = "";

	@Value("${storage.minio.access-key}")
	private String key = "";

	@Value("${storage.minio.secret-key}")
	private String secret = "";

	private static MinioClient minioClient;

	private MinioClient getInstance() {
		if (minioClient == null) {
			try {
				minioClient = new MinioClient(host, key, secret);
			} catch (InvalidEndpointException | InvalidPortException e) {
				log.debug("错误信息:{}", e);
			}
		}
		return minioClient;
	}

	@Override
	public String uploadData(String fileLoalAbcPath, String bucket) throws Exception {
		StorageFileEntity e = this.uploadData(fileLoalAbcPath, null, bucket);
		return e.getFileUrl() ;
	}

	@Override
	public String downloadData(String fileId, String bucket) {
		
		Assert.hasLength(bucket, "bucket不能为空.");
		Assert.hasLength(fileId, "文件路径不能为空.");
		
		try {
			ObjectStat objectStat = getInstance().statObject(bucket, fileId);
			log.debug("object stat:{}" , objectStat);
			
			// 保存本地
			minioClient.getObject(bucket , fileId , fileId);
		} catch (MinioException e) {
			System.out.println("Error occurred: " + e);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (XmlPullParserException e) {
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public boolean deleteData(String fileId, String bucket) {
		
		Assert.hasLength(bucket, "bucket不能为空.");
		Assert.hasLength(fileId, "文件路径不能为空.");
		
		try {
			getInstance().removeObject("mybucket", "myobject");
			
			log.debug("successfully removed {}/{}" , bucket, fileId);
			return true ;
		} catch (Exception e) {
			log.error("fail removed {}/{}" , bucket, fileId);
			return false ; 
		}
	}

	@Override
	public StorageFileEntity uploadData(String fileLoalAbcPath, String fileName, String bucket) throws Exception {

		Assert.hasLength(bucket, "bucket不能为空.");
		Assert.hasLength(fileLoalAbcPath, "文件路径不能为空.");
		Assert.isTrue(fileLoalAbcPath.indexOf(".") != -1, "文件没有后缀或者格式错误.");

		if (StringUtils.isBlank(fileName)) {
			fileName = UUID.randomUUID() + fileLoalAbcPath.substring(fileLoalAbcPath.lastIndexOf("."));
		}

		boolean isExist = getInstance().bucketExists(bucket);
		if (!isExist) {
			minioClient.makeBucket(bucket);
		}

		File f = new File(fileLoalAbcPath);
		MagicMatch match = Magic.getMagicMatch(f,false);
		String contentType = match.getMimeType() ; 
		
		Assert.isTrue(f.exists(), "[" + fileLoalAbcPath + "]文件不存在.");

		String localPath = new SimpleDateFormat("yyyy/MM/dd/").format(new Date());
		String savePath = localPath + fileName;

		minioClient.putObject(bucket, savePath, fileLoalAbcPath, null, null, null, contentType);
		log.debug("{} is successfully uploaded as {} to `{}` bucket.", fileLoalAbcPath, savePath, bucket);

		StorageFileEntity e = new StorageFileEntity();
		e.setFileUrl(savePath);

		return e;
	}

	/**
	 * 查看文件，一天的时间 
	 */
	@Override
	public String presignedUrl(String filePath, String bucket) {
		String url = null ;
		try {
			url = getInstance().presignedGetObject(bucket , filePath , 60 * 60 * 24);
		} catch (Exception e) {
			log.error("获取bucket:{} , filePath:{} 文件失败:{}" , bucket , filePath , e);
		}
		return url ;
	}

}
